#include <buola/gui.h>

#include <buola/image/cgc.h>
#include <buola/gui/cicon.h>

#include <buola/widgets/propertytypes.h>

#include <buola/widgets/ceditbox.h>
#include <buola/widgets/cnumbox.h>
#include <buola/widgets/ccheckbox.h>
#include <buola/widgets/ccombobox.h>

namespace buola { namespace gui {

///////////////////////////////////////////
/////////// CStringPropertyType ///////////
///////////////////////////////////////////

CStringPropertyType::CStringPropertyType()
            : CPropertyType(L"string")
{
}

void CStringPropertyType::InitValue(UAny &pValue)
{
    pValue.Set(std::wstring());
}

void CStringPropertyType::Draw(const UAny &pValue,img::CGC *pGC,
                    const CRect_d &pRect)
{
    pGC->DrawText(pRect.TopLeft()+2,pValue.Get<std::wstring>());
}

CPropertyEditor *CStringPropertyType::GetEditor()
{
    return new Editor(this);
}

void CStringPropertyType::Editor::Start(const UAny &pValue,const PWindow &pParent,
                                        const CRect_d &pRect,const img::CColor &pColor)
{
    mEditBox=new CEditBox;
    mEditBox->sEndEditor.Connect(sEndEdit);
    mEditBox->MoveResize(pRect.TopLeft(),pRect.Size());
    mEditBox->SetCaption(pValue.Get<std::wstring>());
    mEditBox->SetBackColor(pColor);
    mEditBox->SetStyleBit(CWidget::STYLE_NOBORDER|CWidget::STYLE_SMALLFONT|CWidget::STYLE_EDITOR);
    mEditBox->SelectAll();
    mEditBox->Show();
    mEditBox->SetFocus();
    pParent->Place(mEditBox);
}

void CStringPropertyType::Editor::Finish(UAny &pValue)
{
    pValue.Set(mEditBox->GetCaption());
}

////////////////////////////////////////
/////////// CIntPropertyType ///////////
////////////////////////////////////////

CIntPropertyType::CIntPropertyType()
            : CPropertyType(L"int")
{
}

void CIntPropertyType::InitValue(UAny &pValue)
{
    pValue.Set((int)0);
}

void CIntPropertyType::Draw(const UAny &pValue,img::CGC *pGC,
                    const CRect_d &pRect)
{
    pGC->DrawText(pRect.TopLeft()+2,to_wstring(pValue.Get<int>()));
}

CPropertyEditor *CIntPropertyType::GetEditor()
{
    return new Editor(this);
}

void CIntPropertyType::Editor::Start(const UAny &pValue,const PWindow &pParent,
                    const CRect_d &pRect,const img::CColor&)
{
    mNumBox=new CNumBox;
    mNumBox->eEnter.Connect(sEndEdit);
    mNumBox->MoveResize(pRect.TopLeft(),pRect.Size());
    mNumBox->SetValue(pValue.Get<int>());
    mNumBox->SetStyleBit(CWidget::STYLE_NOBORDER|CWidget::STYLE_SMALLFONT);
    mNumBox->SelectAll();
    pParent->Place(mNumBox);
    mNumBox->SetFocus();
}

void CIntPropertyType::Editor::Finish(UAny &pValue)
{
    pValue.Set<int>(mNumBox->GetValue());
}

////////////////////////////////////////////
/////////// CPointerPropertyType ///////////
////////////////////////////////////////////

CPointerPropertyType::CPointerPropertyType()
                : CPropertyType(L"pointer")
{
}

void CPointerPropertyType::InitValue(UAny &pValue)
{
    pValue.Set<void*>(nullptr);
}

void CPointerPropertyType::Draw(const UAny &pValue,img::CGC *pGC,
                    const CRect_d &pRect)
{
    pGC->DrawText(pRect.TopLeft()+2,to_wstring(pValue.Get<void*>()));
}

CPropertyEditor *CPointerPropertyType::GetEditor()
{
    return new Editor(this);
}

void CPointerPropertyType::Editor::Start(const UAny &pValue,const PWindow &pParent,
                    const CRect_d &pRect,const img::CColor&)
{
    mNumBox=new CNumBox;
    mNumBox->eEnter.Connect(sEndEdit);
    mNumBox->MoveResize(pRect.TopLeft(),pRect.Size());
    mNumBox->SetValue((ptrdiff_t)pValue.Get<void*>());
    mNumBox->SetStyleBit(CWidget::STYLE_NOBORDER|CWidget::STYLE_SMALLFONT);
    mNumBox->SelectAll();
    pParent->Place(mNumBox);
    mNumBox->SetFocus();
}

void CPointerPropertyType::Editor::Finish(UAny &pValue)
{
    pValue.Set<void*>((void*)mNumBox->GetValue());
}

///////////////////////////////////////////
/////////// CDoublePropertyType ///////////
///////////////////////////////////////////

CDoublePropertyType::CDoublePropertyType()
                : CPropertyType(L"double")
{
}

void CDoublePropertyType::InitValue(UAny &pValue)
{
    pValue.Set<double>(0.0);
}

void CDoublePropertyType::Draw(const UAny &pValue,img::CGC *pGC,
                    const CRect_d &pRect)
{
    pGC->DrawText(pRect.TopLeft()+2,to_wstring(pValue.Get<double>()));
}

CPropertyEditor *CDoublePropertyType::GetEditor()
{
    return new Editor(this);
}

void CDoublePropertyType::Editor::Start(const UAny &pValue,const PWindow &pParent,
                    const CRect_d &pRect,const img::CColor&)
{
    mNumBox=new CNumBox;
    mNumBox->eEnter.Connect(sEndEdit);
    mNumBox->MoveResize(pRect.TopLeft(),pRect.Size());
    mNumBox->SetValue(pValue.Get<double>());
    mNumBox->SetStyleBit(CWidget::STYLE_NOBORDER|CWidget::STYLE_SMALLFONT|CNumBox::STYLE_DOUBLE);
    mNumBox->SelectAll();
    pParent->Place(mNumBox);
    mNumBox->SetFocus();
}

void CDoublePropertyType::Editor::Finish(UAny &pValue)
{
    pValue.Set<double>(mNumBox->GetDoubleValue());
}

///////////////////////////////////////////
///////// CFileSizePropertyType ///////////
///////////////////////////////////////////

CFileSizePropertyType::CFileSizePropertyType()
                : CPropertyType(L"filesize")
{
}

void CFileSizePropertyType::InitValue(UAny &pValue)
{
    pValue.Set<ssize_t>(0);
}

void CFileSizePropertyType::Draw(const UAny& /*pValue*/,img::CGC *pGC,
                    const CRect_d &pRect)
{
    std::wstring lString;
    //\todo
//  lString << FFileSize(pValue.Get<TFileSize>());

    pGC->DrawText(pRect.TopLeft()+2,lString);
}

CPropertyEditor *CFileSizePropertyType::GetEditor()
{
    return nullptr;
}

///////////////////////////////////////////
///////// CTransferSpeedPropertyType ///////////
///////////////////////////////////////////

CTransferSpeedPropertyType::CTransferSpeedPropertyType()
                : CPropertyType(L"transferspeed")
{
}

void CTransferSpeedPropertyType::InitValue(UAny &pValue)
{
    pValue.Set<double>(0);
}

void CTransferSpeedPropertyType::Draw(const UAny& /*pValue*/,img::CGC *pGC,const CRect_d &pRect)
{
    std::wstring lString;
    //\todo
//  lString << FTransferSpeed(pValue.Get<double>());

    pGC->DrawText(pRect.TopLeft()+2,lString);
}

CPropertyEditor *CTransferSpeedPropertyType::GetEditor()
{
    return nullptr;
}

/////////////////////////////////////////
/////////// CBoolPropertyType ///////////
/////////////////////////////////////////

CBoolPropertyType::CBoolPropertyType()
                : CPropertyType(L"bool")
{
}

void CBoolPropertyType::InitValue(UAny &pValue)
{
    pValue.Set<bool>(false);
}

void CBoolPropertyType::Draw(const UAny &pValue,img::CGC *pGC,
                        const CRect_d &pRect)
{
    pGC->DrawText(pRect.TopLeft()+2,pValue.Get<bool>()?L"true":L"false");
}

CPropertyEditor *CBoolPropertyType::GetEditor()
{
    return new Editor(this);
}

void CBoolPropertyType::Editor::Start(const UAny &pValue,const PWindow &pParent,
                                const CRect_d &pRect,const img::CColor&)
{
    mCheckBox=new CCheckBox;
    mCheckBox->MoveResize(pRect.TopLeft(),pRect.Size());
    mCheckBox->Check(pValue.Get<bool>());
    mCheckBox->SetStyleBit(CWidget::STYLE_NOBORDER|CWidget::STYLE_SMALLFONT);
    pParent->Place(mCheckBox);
    mCheckBox->SetFocus();
}

void CBoolPropertyType::Editor::Finish(UAny &pValue)
{
    pValue.Set<bool>(mCheckBox->IsChecked());
}

//////////////////////////////////////////
/////////// CMultiPropertyType ///////////
//////////////////////////////////////////

CMultiPropertyType::CMultiPropertyType()
                : CPropertyType(L"multi")
{
}

void CMultiPropertyType::InitValue(UAny &pValue)
{
    pValue.Set<int>(0);
}

const std::wstring &CMultiPropertyType::GetOptionName(int pIndex)
{
    return mOptions[pIndex];
}

void CMultiPropertyType::AddOption(int pInt,const std::wstring &pString)
{
    mOptions[pInt]=pString;
}

void CMultiPropertyType::Draw(const UAny &pValue,img::CGC *pGC,
                    const CRect_d &pRect)
{
    if(pValue.HasType<int>())
        pGC->DrawText(pRect.TopLeft()+2,mOptions[pValue.Get<int>()]);
    else if(pValue.HasType<std::wstring>())
        pGC->DrawText(pRect.TopLeft()+2,pValue.Get<std::wstring>());
}

CPropertyEditor *CMultiPropertyType::GetEditor()
{
    return new Editor(this);
}

void CMultiPropertyType::Editor::Start(const UAny &pValue,const PWindow &pParent,
                    const CRect_d &pRect,const img::CColor&)
{
    mComboBox=new CComboBox;
    mComboBox->MoveResize(pRect.TopLeft(),pRect.Size());
    mComboBox->SetStyleBit(CWidget::STYLE_NOBORDER|CWidget::STYLE_SMALLFONT);
    for(std::map<int,std::wstring>::iterator i=mType->mOptions.begin();
                            i!=mType->mOptions.end();++i)
    {
        mComboBox->AddItem(i->second,nullptr,i->first);
    }
    if(pValue.HasType<int>())
    {
        mComboBox->SetCaption(mType->mOptions[pValue.Get<int>()]);
        mComboBox->SelectItemByID(pValue.Get<int>());
    }
    else if(pValue.HasType<std::wstring>())
    {
        mComboBox->SetCaption(pValue.Get<std::wstring>());
        mComboBox->SelectItem(mComboBox->FindItem(pValue.Get<std::wstring>()));
    }
    pParent->Place(mComboBox);
    mComboBox->SetFocus();
}

void CMultiPropertyType::Editor::Finish(UAny &pValue)
{
    pValue.Set<int>(mComboBox->GetSelID());
}

CURIPropertyType::CURIPropertyType()
                : CPropertyType(L"uri")
{
}

void CURIPropertyType::InitValue(UAny &pValue)
{
    pValue.Set(io::CURI());
}

void CURIPropertyType::Draw(const UAny &pValue,img::CGC *pGC,const CRect_d &pRect)
{
    pGC->DrawText(pRect.TopLeft()+2,pValue.Get<io::CURI>().ToWString());
}

CPropertyEditor *CURIPropertyType::GetEditor()
{
    return new Editor(this);
}

void CURIPropertyType::Editor::Start(const UAny &pValue,const PWindow &pParent,
                    const CRect_d &pRect,const img::CColor &pColor)
{
    /*
    mURLBox=new CURIBox;
    mURLBox->eEnter.Connect(sEndEdit);
    mURLBox->Create(pParent,pRect.TopLeft(),pRect.Size());
    mURLBox->SetCaption(pValue.Get<std::wstring>());
    mURLBox->SetStyleBit(CWidget::STYLE_NOBORDER|CWidget::STYLE_SMALLFONT);
    mURLBox->SelectAll();
    mURLBox->Show();
    mURLBox->SetFocus();
    */
}

void CURIPropertyType::Editor::Finish(UAny &pValue)
{
    /*
    pValue.Set<CURI>(mURLBox->GetCaption());

    mURLBox->Destroy();
    delete mURLBox;
    */
}

/*namespace gui*/ } /*namespace buola*/ }
